/*******************************************************************************
 * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
 * @file     communicate_Uart.c
 * @author   UartTFT Application Team
 * @version  V0.0.1
 * @date     2023-01-11
 * @brief    This file provides UartTFT Application display function
 ********************************************************************************/

#include "communicate_Uart.h"
#include "uiEncoder.h"
/********************************************************************************
 * Function Name : LT_ReceiveCmd
 * Description   : Instruction processing.
 * Input         : - buf: Buffer address of instruction
 * Output        : None
 * Return        : None
 *********************************************************************************/
void LT_ReceiveCmd(uint8_t *buf)
{
	uint8_t cmd = 0, temp = 0, num = 0, cnt = 0;
	uint8_t rebuf[2100];
	uint16_t i = 0, j = 0;
	uint16_t rxCrc, mcuCrc;
	uint16_t addr = 0xFFFF;
	uint16_t count1 = 0, count2 = 0;
	uint32_t eflash_addr = 0, len = 0;
	uint32_t File_CRC = 0;


	gUsartRx.Flag = 0;

	if (CRC_Enable_Flag)
	{
		rxCrc = buf[gUsartRx.Count - 1];
		rxCrc = (rxCrc << 8) + buf[gUsartRx.Count - 2];
		//mcuCrc = CRC16(&buf[1], gUsartRx.Count - 3);
		if (buf[0] != 0)
		{
			mcuCrc = CRC16(&buf[1], gUsartRx.Count - 3);
		}
		else if (buf[0] == 0)
		{
			mcuCrc = CRC16(&buf[3], gUsartRx.Count - 5);
		}
	}
	else
		rxCrc = mcuCrc;

	if (buf[0] != 0)
	{

		cmd = buf[1];
		if (cmd == 0x03 || cmd == 0x10)
		{
			JiYi_time=1;JiYi_flag=1;
			if (rxCrc == mcuCrc) // CRC OK
			{
				if (CRC_Enable_Flag && CRC_Feedback_Flag) // CRC feedback is the default
				{
					rebuf[3] = cmd;
					rebuf[4] = 0xFF;
					LT_SendData_CRC_Frame(rebuf, 2);
				}

				/***************************Read instruction***************************/
				if (cmd == 0x03)
				{
					addr = (buf[2] << 8) | buf[3];
					len = (buf[4] << 8) | buf[5];

					Var_AddrRemapping(&addr);

					for (i = 0; i < 5; i++)
					{
						rebuf[3 + i] = buf[1 + i];
					}

					if (addr < VAR_ADDR_S) // Variable address
					{
						for (i = 0; i < len; i++)
						{
							rebuf[8 + 2 * i] = var[2 * (addr + i)];
							rebuf[9 + 2 * i] = var[2 * (addr + i) + 1];
						}
					}
					else if (addr >= VAR_ADDR_S && addr <= VAR_ADDR_E)
					{

						if (addr + len >= VAR_TIME || addr <= (VAR_TIME + 5))
						{
							var[VAR_TIME * 2 + 1] = calendar.w_year - 2000;
							var[(VAR_TIME + 1) * 2 + 1] = calendar.w_month;
							var[(VAR_TIME + 2) * 2 + 1] = calendar.w_date;
							var[(VAR_TIME + 3) * 2 + 1] = calendar.hour;
							var[(VAR_TIME + 4) * 2 + 1] = calendar.min;
							var[(VAR_TIME + 5) * 2 + 1] = calendar.sec;
						}
						for (i = 0; i < len; i++)
						{
							rebuf[8 + 2 * i] = var[2 * (addr + i)];
							rebuf[9 + 2 * i] = var[2 * (addr + i) + 1];
						}
					}

					LT_SendData_CRC_Frame(rebuf, 5 + len * 2);
				}
				/***************************Write instructions***************************/
				else if (cmd == 0x10)
				{
					addr = (buf[2] << 8) | buf[3];
					if (CRC_Enable_Flag)
						len = (buf[0] - 2 - 3) / 2;
					else
						len = (buf[0] - 3) / 2;

					Var_AddrRemapping(&addr);

					if (addr < VAR_ADDR_S) // Variable address
					{
						// save data
						for (i = 0; i < len; i++)
						{
							var[2 * (addr + i)] = buf[4 + 2 * i];
							var[2 * (addr + i) + 1] = buf[5 + 2 * i];
						}
					}
					else if (addr >= VAR_ADDR_S && addr <= VAR_ADDR_E)
					{

						for (i = 0; i < len; i++)
						{
							var[2 * (addr + i)] = buf[4 + 2 * i];
							var[2 * (addr + i) + 1] = buf[5 + 2 * i];
						}

						for (i = 0; i < len;)
						{
							if ((addr + i) == VAR_PAGE) // page
							{
								if (pic_id != (var[VAR_PAGE * 2] << 8 | var[VAR_PAGE * 2 + 1]))
								{
									Display_page(var[VAR_PAGE * 2] << 8 | var[VAR_PAGE * 2 + 1]);
								}
								i++;
							}
							else if ((addr + i) == VAR_BL) // backlight
							{
								if (var[VAR_BL * 2 + 1] > 63)
									var[VAR_BL * 2 + 1] = 63;

								LT_BacklightSet(gDutyBuf[var[VAR_BL * 2 + 1]]);
								Backlight_flag = 1;

								i++;
							}
							else if ((addr + i) == VAR_TIME) // time
							{
								if (var[VAR_TIME * 2 + 1] > 99)
									var[VAR_TIME * 2 + 1] = 99;
								if (var[(VAR_TIME + 1) * 2 + 1] > 12)
									var[(VAR_TIME + 1) * 2 + 1] = 12;
								if (var[(VAR_TIME + 2) * 2 + 1] > 31)
									var[(VAR_TIME + 2) * 2 + 1] = 31;
								if (var[(VAR_TIME + 3) * 2 + 1] > 23)
									var[(VAR_TIME + 3) * 2 + 1] = 23;
								if (var[(VAR_TIME + 4) * 2 + 1] > 59)
									var[(VAR_TIME + 4) * 2 + 1] = 59;
								if (var[(VAR_TIME + 5) * 2 + 1] > 59)
									var[(VAR_TIME + 5) * 2 + 1] = 59;

								RTC_Set(2000 + var[VAR_TIME * 2 + 1], var[(VAR_TIME + 1) * 2 + 1], var[(VAR_TIME + 2) * 2 + 1], var[(VAR_TIME + 3) * 2 + 1], var[(VAR_TIME + 4) * 2 + 1], var[(VAR_TIME + 5) * 2 + 1]);
								i += 6;
							}
							else if ((addr + i) == VAR_TIMESET) // time setting
							{
								i++;
							}
							else if ((addr + i) == VAR_RSIZE_9) // NULL
							{
								i++;
							}
							else if ((addr + i) == VAR_WAV) // WAV
							{
								Wav_DAC_Init((var[VAR_WAV * 2] << 8) | var[VAR_WAV * 2 + 1]);
								i++;
							}
							else if ((addr + i) == VAR_VOLUME) // sound volume
							{
								if (var[2 * VAR_VOLUME + 1] > 16)
									wav_reduce_para = 16;
								else
									wav_reduce_para = var[2 * VAR_VOLUME + 1];
								i++;
							}
							else if ((addr + i) == VAR_RTP) // RTP calibration
							{
								if (var[VAR_RTP * 2 + 1] == 0x5A)
								{
	#if (LT_TOUCH_FLAG == 1)
									LT_TpAdjust();
	#endif
									var[VAR_RTP * 2 + 1] = 0x00;
									Display_page(((var[VAR_PAGE * 2] << 8) | var[VAR_PAGE * 2 + 1]));
								}
								i++;
							}
							else if ((addr + i) == VAR_KEY) // Key code trigger
							{

								Button_Key_Code = (var[VAR_KEY * 2] << 8) | var[VAR_KEY * 2 + 1];
								Button_Key_Code_Flag = 1;
								i++;
							}
							else if ((addr + i) == VAR_BLAUTO)
							{
								if(var[2 * VAR_BLAUTO + 1] == 1)
								{
									if (Backlight_flag == 0)
									{
										Backlight_count = 0;
										Backlight_flag = 1;
										LT_BacklightSet(gDutyBuf[var[VAR_BL * 2 + 1]]);
									}
								}
								else if (var[2 * VAR_BLAUTO + 1] == 0)
								{
									Backlight_count = 0;
									Backlight_flag = 0;
									LT_BacklightSet(gDutyBuf[var[VAR_BL * 2 + 1]]);
								}
								i++;
							}
							else if ((addr + i) == VAR_BLSLEEP)
							{
								if (Backlight_flag == 0 && var[2 * VAR_BLAUTO + 1] == 1)
								{
									LT_BacklightSet(gDutyBuf[var[VAR_BLSLEEP * 2 + 1]]);
								}
								i++;
							}
							else if ((addr + i) == VAR_MCURESET)
							{
								if (var[2 * VAR_MCURESET] == 0xAA && var[2 * VAR_MCURESET + 1] == 0x55)
								{
									var[2 * VAR_MCURESET] = 0;
									var[2 * VAR_MCURESET + 1] = 0;
									APP(0x60000000);
								}
								i++;
							}
							else if ((addr + i) == VAR_MTLANGUAGE)
							{
								if (var[2 * VAR_MTLANGUAGE + 1] < multi_language_count && var[2 * VAR_MTLANGUAGE + 1] != multi_language)
								{
									uint32_t language_sum = 0,language_count = 0,L_count = 0;
									uint32_t language_addr = 0,L_addr,L_len = 0;
									uint16_t L_num;

									multi_language = var[2 * VAR_MTLANGUAGE + 1];

									LT_ReadFlash_UI(rebuf,addr_index[18] + 8 * multi_language,8);
									language_addr = (rebuf[0]) + (rebuf[1] << 8) + (rebuf[2] << 16) + (rebuf[3] << 24);
									language_sum = (rebuf[4]) + (rebuf[5] << 8) + (rebuf[6] << 16) + (rebuf[7] << 24);

									if (language_sum - language_count >=2048)
											LT_ReadFlash_UI(rebuf,language_addr,2048);
									else
										LT_ReadFlash_UI(rebuf,language_addr,language_sum);

									while(1)
									{
										if (L_count + 4 > 2048)
										{
											if (language_sum - language_count >= 2048)
												LT_ReadFlash_UI(rebuf,language_addr + language_count,2048);
											else
												LT_ReadFlash_UI(rebuf,language_addr + language_count,language_sum - language_count);
											L_count = 0;

										}
										L_addr = rebuf[L_count] + (rebuf[L_count + 1] << 8);
										L_len = rebuf[L_count + 2] + (rebuf[L_count + 3] << 8);
										L_count = L_count + 4;

										if(L_count + L_len > 2048)
										{
											if (language_sum - (language_count + 4) >= 2048)
												LT_ReadFlash_UI(rebuf,language_addr + language_count + 4,2048);
											else
												LT_ReadFlash_UI(rebuf,language_addr + language_count + 4 ,language_sum - (language_count + 4));
											L_count = 0;
										}

										for (uint16_t ll = 0; ll < L_len; ll++)
										{
											var[L_addr * 2 + ll] = rebuf[L_count + ll];
										}
										language_count += L_len + 4;
										L_count += L_len;

										if(language_count >= language_sum)
											break;
									}

									if(Pop_up_flag == 1)
									{
										Display_pop_up(Pop_up_id,Pop_up_x,Pop_up_y);
									}
									else Display_page(pic_id);
								}
								else
									var[2 * VAR_MTLANGUAGE + 1] = multi_language;

								i++;
							}
							else if ((addr + i) == VAR_UI_CHANGE)
							{
								if(lt_screen_dir != var[VAR_UI_CHANGE * 2 + 1])
									LT_LCD_screen_dir(var[VAR_UI_CHANGE * 2 + 1]);
								i++;
							}
							else if ((addr + i) == VAR_UI_UPDATE)
							{
								if (var[2 * VAR_UI_UPDATE + 1] == 0 && UI_update == 1)
								{
									UI_update = 0;
									Address_Index(); 		// Get address index
									LT_ReadParam();
									if (Start_page > addr_index[7])
										Display_page(0);
									else
										Display_page(Start_page);
								}
								else if (var[2 * VAR_UI_UPDATE + 1] == 1 && UI_update == 0)
								{
									LT268_TFT_FillColor(0,0,LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1,Blue2);
									LT268_TFT_ShowAscll(0, 10, 24, 0, Red, White, (uint8_t *)"Update Flash");
									UI_update = 1;
								}
								i++;
							}
							else
							{
								i++;
							}
						}
					}
					else if (addr >= VAR_CURVE_WS && addr <= VAR_CURVE_WE) // Curve channel address for write
					{
						temp = addr & 0xFFF;
						for (i = 0; i < CURVE_SIZE; i++)
						{
							if (temp & (1 << i))
								num++; // Record the number of channel groups
						}

						i = 0;
						j = 0;
						while (j < len) // Store data to corresponding channels respectively
						{
							if (temp & (1 << i))
							{
								Curve_buff[i][Curve_count[i]] = buf[4 + 2 * j] << 8 | buf[5 + 2 * j];
								Curve_count[i]++;
								if (Curve_count[i] >= 1024)
								{
									Curve_count[i] = 0;
								}
								curve_update_flag[i] = 1;
								j++;
							}
							i++;
							if (i >= CURVE_SIZE)
								i = 0;
						}

						if (len % num) // When multi-channel buffer data is triggered, if some channel data is missing, the missing part will be supplemented
						{
							for (i = 0; i < CURVE_SIZE; i++)
							{
								if (temp & (1 << i))
									cnt++;
								if (cnt > len % num && (temp & (1 << i)))
								{
									if (Curve_count[i] != 0)
										Curve_buff[i][Curve_count[i]] = Curve_buff[i][Curve_count[i] - 1];
									else
										Curve_buff[i][0] = Curve_buff[i][1023];

									Curve_count[i]++;
									if (Curve_count[i] >= 1024)
									{
										Curve_count[i] = 0;
									}
								}
							}
						}
					}
					else if (addr >= VAR_CURVE_CS && addr <= VAR_CURVE_CE) // Curve channel address for clear
					{
						temp = addr & 0xFFF;

						i = 0;
						j = 0;
						for (i = 0; i < CURVE_SIZE; i++) // clear data
						{
							if (temp & (1 << i))
							{
								for (j = 0; j < 1024; j++)
								{
									Curve_buff[i][j] = 0x00;
								}

								Curve_count[i] = 0;
								curve_update_flag[i] = 1;
							}
						}
					}
				}
			}
			else // CRC NG
			{
				if (CRC_Feedback_Flag) // CRC feedback is the default
				{
					rebuf[3] = cmd;
					rebuf[4] = 0x00;
					LT_SendData_CRC_Frame(rebuf, 2);
				}
			}
		}
		else if (cmd == 0x61 || cmd == 0x62 || cmd == 0x65 || cmd == 0x66)
		{

		}
	}
	else if (buf[0] == 0)//Length extension identifier��������չ��ʶ��
	{
		cmd = buf[3];
		if (rxCrc == mcuCrc) // CRC OK
		{
			if (CRC_Enable_Flag && CRC_Feedback_Flag) // CRC feedback is the default
			{
				rebuf[3] = cmd;
				rebuf[4] = 0xFF;
				LT_SendData_CRC_Frame(rebuf, 2);
			}

			if (cmd == 0x61)//EFlash write command
			{
				len = (buf[1] << 8) | buf[2];
				eflash_addr = 0x804B000 + ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

				/*��Ҫһ�ν�4k����д��*/
				if(g_upflag==0)
				{
					if(g_upflag==0) memcpy(g_upbuffer,&buf[8],len-7);
					else if(g_upflag==1) memcpy(&g_upbuffer[2048],&buf[8],len-7);
					g_upflag++;
				}

				if(g_upflag == 2)
				{
					g_upflag = 0;
					EFlash_Init();
					EFLASH_Write(eflash_addr,g_upbuffer,4096);
				}


				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				rebuf[10] = 0x4F;
				rebuf[11] = 0x4B;

				LT_SendFlashData_CRC_Frame(rebuf, 7);

			}
			else if (cmd == 0x62)//EFlash read command
			{
				len = (buf[8] << 8) | buf[9];
				if (len > 2048) len = 2048;
				eflash_addr = 0x804B000 + ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

				EFlash_Read(eflash_addr,&rebuf[10],len);


				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				LT_SendFlashData_CRC_Frame(rebuf, len + 5);

			}
			else if (cmd == 0x63)//EFlash check crc
			{
				len = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
				count1 = len / 2048;
				count2 = len % 2048;
				eflash_addr = 0x804B000 + ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

				for(i = 0; i < count1; i++)
				{
					EFlash_Read(eflash_addr + 2048 * i,rebuf,2048);
					File_CRC = GetCrc32(rebuf,2048,File_CRC);
				}
				if(count2 > 0)
				{
					EFlash_Read(eflash_addr + 2048 * i,rebuf,count2);
					File_CRC = GetCrc32(rebuf,count2,File_CRC);
				}

				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				rebuf[10] = (File_CRC >> 24) & 0xFF;
				rebuf[11] = (File_CRC >> 16) & 0xFF;
				rebuf[12] = (File_CRC >> 8) & 0xFF;
				rebuf[13] = File_CRC & 0xFF;
				LT_SendFlashData_CRC_Frame(rebuf, 9);

			}
			else if (cmd == 0x64)//Spi flash write command
			{
				len = (buf[1] << 8) | buf[2];
				eflash_addr = ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

			    LT_WinbondFlash_write_2K(&buf[8],eflash_addr,len-7);

				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				rebuf[10] = 0x4F;
				rebuf[11] = 0x4B;

				LT_SendFlashData_CRC_Frame(rebuf, 7);

			}
			else if (cmd == 0x65)//Spi flash read command
			{
				len = (buf[8] << 8) | buf[9];
				if (len > 2048) len = 2048;
				eflash_addr = ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

				LT_ReadFlash_DMA(&rebuf[10],eflash_addr,len);

				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				LT_SendFlashData_CRC_Frame(rebuf, len + 5);

			}
			else if (cmd == 0x66)//Spi flash check crc
			{
				len = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
				count1 = len / 2048;
				count2 = len % 2048;
				eflash_addr = ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);

				for(i = 0; i < count1; i++)
				{
					LT_ReadFlash_DMA(rebuf,eflash_addr + 2048 * i,2048);
					File_CRC = GetCrc32(rebuf,2048,File_CRC);
				}

				if(count2 > 0)
				{
					LT_ReadFlash_DMA(rebuf,eflash_addr + 2048 * i,count2);
					File_CRC = GetCrc32(rebuf,count2,File_CRC);
				}


				rebuf[5] = cmd;
				rebuf[6] = buf[4];
				rebuf[7] = buf[5];
				rebuf[8] = buf[6];
				rebuf[9] = buf[7];
				rebuf[10] = (File_CRC >> 24) & 0xFF;
				rebuf[11] = (File_CRC >> 16) & 0xFF;
				rebuf[12] = (File_CRC >> 8) & 0xFF;
				rebuf[13] = File_CRC & 0xFF;
				LT_SendFlashData_CRC_Frame(rebuf, 9);

			}
		}
		else // CRC NG
		{
			if (CRC_Feedback_Flag) // CRC feedback is the default
			{
				rebuf[3] = cmd;
				rebuf[4] = 0x00;
				LT_SendData_CRC_Frame(rebuf, 2);
			}
		}
	}

	gUsartRx.Flag = 0;
	gUsartRx.Count = 0; // Clear to receive the next data
	memset(gUsartRx.Buf,0,sizeof(gUsartRx.Buf));// Clear receive buffer
}
